/**
 * create by zhangpu
 * date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.yinsheng.marshall;

import com.acooly.core.utils.Money;
import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.anotation.ApiItem;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.ApiMessage;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.api.util.ApiTypes;
import com.acooly.module.openapi.client.api.util.MoneyDeserializer;
import com.acooly.module.openapi.client.provider.yinsheng.YinShengConstants;
import com.acooly.module.openapi.client.provider.yinsheng.domain.YinShengResponse;
import com.acooly.module.openapi.client.provider.yinsheng.enums.YinShengServiceEnum;
import com.acooly.module.openapi.client.provider.yinsheng.partner.YinShengPartnerIdLoadManager;
import com.acooly.module.openapi.client.provider.yinsheng.utils.JsonMarshallor;
import com.acooly.module.safety.Safes;
import com.acooly.module.safety.exception.SignatureVerifyException;
import com.acooly.module.safety.key.KeyLoadManager;
import com.acooly.module.safety.signature.SignTypeEnum;
import com.acooly.module.safety.support.KeyStoreInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author zhangpu
 */
@Service
@Slf4j
public class YinShengResponseUnmarshall extends YinShengMarshallSupport implements ApiUnmarshal<YinShengResponse, String> {

    private static final Logger logger = LoggerFactory.getLogger(YinShengResponseUnmarshall.class);

    @Resource(name = "yinShengMessageFactory")
    private MessageFactory messageFactory;

    @Resource(name = "yinShengPartnerIdLoadManager")
    private YinShengPartnerIdLoadManager partnerIdLoadManager;

    private static JsonMarshallor jsonMarshallor = JsonMarshallor.INSTANCE;

    @Autowired
    private KeyLoadManager keyStoreLoadManager;


    @SuppressWarnings("unchecked")
    @Override
    public YinShengResponse unmarshal(String message, String serviceName) {
        try {
            logger.info("响应报文:{}", message);
            // 验签
            LinkedHashMap<String, String> responseMap = JSON.parseObject(message, new TypeReference<LinkedHashMap<String, String>>() {
            }, Feature.OrderedField);
            String signature = responseMap.get(YinShengConstants.SIGN);
            String plain = responseMap.get(YinShengConstants.YS_SERVICE_RESPONSE_MAP.get(serviceName));
            LinkedHashMap<String, String> busiResMap = JSON.parseObject(plain, new TypeReference<LinkedHashMap<String, String>>() {
            }, Feature.OrderedField);
            String parnerId = partnerIdLoadManager.load(busiResMap.get(YinShengConstants.ORDER_NO_NAME));
            KeyStoreInfo keyStoreInfo = keyStoreLoadManager.load(parnerId, YinShengConstants.PROVIDER_NAME);
            Safes.getSigner(SignTypeEnum.Cert).verify(plain,keyStoreInfo,signature);
            log.info("验签成功");
            return doUnmarshall(busiResMap, serviceName);
        } catch (Exception e) {
            String emessage = String.format("解析响应报文错误:%s", e.getMessage());
            if(e instanceof SignatureVerifyException) {
                emessage = "验签失败"+e.getMessage();
            }
            throw new ApiClientException(emessage);
        }
    }

    protected YinShengResponse doUnmarshall(Map<String, String> message, String serviceName) {
        YinShengResponse response = (YinShengResponse) messageFactory.getResponse(YinShengServiceEnum.find(serviceName).getKey());
        Set<Field> fields = Reflections.getFields(response.getClass());
        String key = null;
        for (Field field : fields) {
            Object convertedValue = null;
            ApiItem apiItem = field.getAnnotation(ApiItem.class);
            if (apiItem != null && Strings.isNotBlank(apiItem.value())) {
                key = apiItem.value();
            } else {
                key = field.getName();
            }
            String newValue = message.get(key);
            if (ApiTypes.isSimpleType(field.getType())) {
                convertedValue = message.get(key);
            }else if(ApiTypes.isCollection(field)) {
                ParserConfig.getGlobalInstance().putDeserializer(Money.class, MoneyDeserializer.instance);
                Type gt = field.getGenericType ();
                if(gt instanceof ParameterizedType){
                    Type genericType = ((ParameterizedType) gt).getActualTypeArguments ()[0];
                    if(genericType instanceof Class){
                        convertedValue = jsonMarshallor.parseArray(newValue,(Class) genericType);
                    }
                    else{
                        convertedValue = jsonMarshallor.parseArray(newValue,Reflections.getClassGenricType(response.getClass()));
                    }
                }
            }
            Reflections.invokeSetter(response, field.getName(), convertedValue);
        }
        response.setMethod(YinShengServiceEnum.find(serviceName).getCode());
        return response;
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }


}
